home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 4
/
Aminet 4 - November 1994.iso
/
aminet
/
comm
/
term
/
term41source.lha
/
Extras
/
Source
/
term-Source.lha
/
termAux.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-18
|
74KB
|
4,006 lines
/*
** termAux.c
**
** Miscellaneous support routines
**
** Copyright © 1990-1994 by Olaf `Olsen' Barthel
** All Rights Reserved
*/
#include "termGlobal.h"
/* This variable stores the current state of the
* dialing menu items.
*/
STATIC BYTE DialItemsAvailable = TRUE;
/* Current timer state. */
STATIC BYTE TimerRunning = FALSE;
/* StripSpaces(STRPTR String):
*
* Strip leading and trailing spaces from a string.
*/
VOID __regargs
StripSpaces(STRPTR String)
{
if(String)
{
STRPTR To = String;
WORD Len;
while(*String == ' ')
String++;
if(Len = strlen(String))
{
while(Len > 0 && String[Len - 1] == ' ')
Len--;
while(Len--)
*To++ = *String++;
}
*To = 0;
}
}
/* ReplaceWindowInfo(struct WindowInfo *NewInfo):
*
* Drop the window info into the right place.
*/
VOID __regargs
ReplaceWindowInfo(struct WindowInfo *NewInfo)
{
WORD i;
for(i = 0 ; i < WINDOW_COUNT ; i++)
{
if(WindowInfoTable[i] . ID == NewInfo -> ID)
{
CopyMem(NewInfo,&WindowInfoTable[i],sizeof(struct WindowInfo));
break;
}
}
}
/* PutWindowInfo():
*
* Store window size and position relative to
* the main window.
*/
VOID __regargs
PutWindowInfo(UBYTE ID,LONG Left,LONG Top,LONG Width,LONG Height)
{
struct WindowInfo *Info;
WORD i;
LONG WindowLeft,
WindowTop,
WindowWidth,
WindowHeight;
ULONG IntuiLock;
for(i = 0 ; i < WINDOW_COUNT ; i++)
{
if(WindowInfoTable[i] . ID == ID)
{
Info = &WindowInfoTable[i];
break;
}
}
IntuiLock = LockIBase(NULL);
WindowLeft = Window -> LeftEdge;
WindowTop = Window -> TopEdge;
WindowWidth = Window -> Width;
WindowHeight = Window -> Height;
UnlockIBase(IntuiLock);
Forbid();
Info -> WindowFlags = NULL;
if(WindowWidth == Width && WindowLeft == Left)
Info -> WindowFlags |= WC_EXPANDWIDTH;
else
{
if(Left == WindowLeft + WindowWidth)
Info -> WindowFlags |= WC_ALIGNSIDE;
if(WindowLeft == Left)
Info -> WindowFlags |= WC_ALIGNLEFT;
if(WindowLeft + WindowWidth == Left + Width)
Info -> WindowFlags |= WC_ALIGNRIGHT;
}
if(WindowHeight == Height && WindowTop == Top)
Info -> WindowFlags |= WC_EXPANDHEIGHT;
else
{
if(Top == WindowTop + WindowHeight)
Info -> WindowFlags |= WC_ALIGNBELOW;
if(WindowTop == Top)
Info -> WindowFlags |= WC_ALIGNTOP;
if(WindowTop + WindowHeight == Top + Height)
Info -> WindowFlags |= WC_ALIGNBOTTOM;
}
Info -> Left = Left;
Info -> Top = Top;
Info -> Width = Width;
Info -> Height = Height;
Permit();
}
/* GetWindowInfo():
*
* Set the window size and position in relation to
* the main window.
*/
VOID __regargs
GetWindowInfo(UBYTE ID,LONG *Left,LONG *Top,LONG *Width,LONG *Height,LONG DefWidth,LONG DefHeight)
{
struct WindowInfo *Info;
WORD i;
LONG WindowLeft,
WindowTop,
WindowWidth,
WindowHeight;
ULONG IntuiLock;
if(DefWidth && DefWidth < Window -> Width / 2)
DefWidth = Window -> Width / 2;
if(DefHeight && DefHeight < Window -> Height / 2)
DefHeight = Window -> Height / 2;
for(i = 0 ; i < WINDOW_COUNT ; i++)
{
if(WindowInfoTable[i] . ID == ID)
{
Info = &WindowInfoTable[i];
break;
}
}
IntuiLock = LockIBase(NULL);
WindowLeft = Window -> LeftEdge;
WindowTop = Window -> TopEdge;
WindowWidth = Window -> Width;
WindowHeight = Window -> Height;
UnlockIBase(IntuiLock);
Forbid();
if(*Width)
{
if(Info -> Width)
*Left = Info -> Left;
else
*Left = WindowLeft + (WindowWidth - *Width) / 2;
}
else
{
if(DefWidth && !Info -> Width)
{
*Width = DefWidth;
*Left = WindowLeft + (WindowWidth - *Width) / 2;
}
else
{
if(Info -> Width)
{
*Width = Info -> Width;
*Left = Info -> Left;
}
else
{
/* *Width = WindowWidth / 2;*/
/* *Left = WindowLeft + WindowWidth / 4;*/
*Width = WindowWidth;
*Left = WindowLeft;
}
}
}
if(*Height)
{
if(Info -> Height)
*Top = Info -> Top;
else
*Top = WindowTop + (WindowHeight - *Height) / 2;
}
else
{
if(DefHeight && !Info -> Height)
{
*Height = DefHeight;
*Top = WindowTop + (WindowHeight - *Height) / 2;
}
else
{
if(Info -> Height)
{
*Height = Info -> Height;
*Top = Info -> Top;
}
else
{
/* *Height = WindowHeight / 2;*/
/* *Top = WindowTop + WindowHeight / 4;*/
*Height = WindowHeight;
*Top = WindowTop;
}
}
}
if(Info -> WindowFlags & WC_ALIGNSIDE)
*Left = WindowLeft + WindowWidth;
if(Info -> WindowFlags & WC_ALIGNBELOW)
*Top = WindowTop + WindowHeight;
if(Info -> WindowFlags & WC_ALIGNLEFT)
*Left = WindowLeft;
if(Info -> WindowFlags & WC_ALIGNTOP)
*Top = WindowTop;
if(Info -> WindowFlags & WC_ALIGNRIGHT)
*Left = WindowLeft + WindowWidth - *Width;
if(Info -> WindowFlags & WC_ALIGNBOTTOM)
*Top = WindowTop + WindowHeight - *Height;
if(Info -> WindowFlags & WC_EXPANDWIDTH)
*Width = WindowWidth;
if(Info -> WindowFlags & WC_EXPANDHEIGHT)
*Height = WindowHeight;
Permit();
}
/* GetDPI(ULONG Mode,ULONG *X_DPI,ULONG *Y_DPI):
*
* Get screen DPI resolution values.
*/
VOID __regargs
GetDPI(ULONG Mode,ULONG *X_DPI,ULONG *Y_DPI)
{
struct DisplayInfo DisplayInfo;
if(GetDisplayInfoData(NULL,(APTR)&DisplayInfo,sizeof(struct DisplayInfo),DTAG_DISP,Mode))
{
*X_DPI = (35 * 140) / DisplayInfo . PixelSpeed;
*Y_DPI = (*X_DPI * DisplayInfo . Resolution . x) / DisplayInfo . Resolution . y;
}
else
*X_DPI = *Y_DPI = 72;
}
/* AddProtection(STRPTR FileName,ULONG Mask):
*
* Set bits in the protection mask of a file.
*/
VOID __regargs
AddProtection(STRPTR Name,ULONG Mask)
{
struct FileInfoBlock *FileInfo;
if(FileInfo = (struct FileInfoBlock *)AllocDosObject(DOS_FIB,TAG_DONE))
{
BPTR FileLock;
if(FileLock = Lock(Name,ACCESS_READ))
{
if(Examine(FileLock,FileInfo))
{
UnLock(FileLock);
SetProtection(Name,FileInfo -> fib_Protection | Mask);
}
else
UnLock(FileLock);
}
FreeDosObject(DOS_FIB,FileInfo);
}
}
/* GetPubScreenName(struct Screen *Screen,STRPTR Name):
*
* Get the name of a public screen.
*/
BYTE __regargs
GetPubScreenName(struct Screen *Screen,STRPTR Name)
{
struct List *PubScreenList;
struct PubScreenNode *ScreenNode;
PubScreenList = LockPubScreenList();
for(ScreenNode = (struct PubScreenNode *)PubScreenList -> lh_Head ; ScreenNode -> psn_Node . ln_Succ ; ScreenNode = (struct PubScreenNode *)ScreenNode -> psn_Node . ln_Succ)
{
if(ScreenNode -> psn_Screen == Screen)
{
strcpy(Name,ScreenNode -> psn_Node . ln_Name);
UnlockPubScreenList();
return(TRUE);
}
}
UnlockPubScreenList();
return(FALSE);
}
/* InitSinglePort(struct MsgPort *Port):
*
* Initialize a plain MsgPort (as created on the stack) for
* usage. Don't try this at home, kids!
*/
VOID __regargs
InitSinglePort(struct MsgPort *Port)
{
memset(Port,0,sizeof(struct MsgPort));
Port -> mp_Flags = PA_SIGNAL;
Port -> mp_SigBit = SIGB_SINGLE;
Port -> mp_SigTask = SysBase -> ThisTask;
NewList(&Port -> mp_MsgList);
}
/* GoodStream(BPTR Stream):
*
* Check to see whether the current input file
* is an interactive stream.
*/
BYTE __regargs
GoodStream(BPTR Stream)
{
if(!Stream)
{
struct Process *ThisProcess = (struct Process *)SysBase -> ThisTask;
Stream = ThisProcess -> pr_CIS;
}
if(Stream)
{
struct FileHandle *Handle = (struct FileHandle *)BADDR(Stream);
if(Handle -> fh_Type)
{
if(IsInteractive(Stream))
return(TRUE);
}
}
return(FALSE);
}
/* GetProgramIcon():
*
* Try to find the icon of the program.
*/
struct DiskObject *
GetProgramIcon()
{
struct DiskObject *Icon = NULL;
/* Run from Workbench? */
if(WBenchMsg)
{
/* Sanity check. */
if(WBenchMsg -> sm_ArgList)
{
/* Yet another sanity check. */
if(WBenchMsg -> sm_ArgList -> wa_Name)
{
/* Try to find the icon in the current directory. */
if(Icon = GetDiskObjectNew(WBenchMsg -> sm_ArgList -> wa_Name))
{
if(Icon -> do_Type != WBTOOL)
{
FreeDiskObject(Icon);
Icon = NULL;
}
}
if(!Icon)
{
BPTR NewLock;
/* Move to the directory the
* program was run from.
*/
if(NewLock = Lock("PROGDIR:",ACCESS_READ))
{
BPTR OldLock;
OldLock = CurrentDir(NewLock);
/* Try to fetch the icon, use the
* default name if necessary.
*/
if(Icon = GetDiskObjectNew(WBenchMsg -> sm_ArgList -> wa_Name))
{
if(Icon -> do_Type != WBTOOL)
{
FreeDiskObject(Icon);
Icon = NULL;
}
}
if(!Icon)
{
if(Icon = GetDiskObjectNew("term"))
{
if(Icon -> do_Type != WBTOOL)
{
FreeDiskObject(Icon);
Icon = NULL;
}
}
}
CurrentDir(OldLock);
UnLock(NewLock);
}
}
}
}
}
/* Still no success. */
if(!Icon)
{
/* Use the default names. */
if(Icon = GetDiskObjectNew("term"))
{
if(Icon -> do_Type != WBTOOL)
{
FreeDiskObject(Icon);
Icon = NULL;
}
}
if(!Icon)
{
if(Icon = GetDiskObjectNew("PROGDIR:term"))
{
if(Icon -> do_Type != WBTOOL)
{
FreeDiskObject(Icon);
Icon = NULL;
}
}
}
}
return(Icon);
}
/* GetPenIndex(LONG Pen):
*
* Get the table index corresponding to an on-screen
* text rendering pen.
*/
LONG __regargs
GetPenIndex(LONG Pen)
{
LONG i;
for(i = 0 ; i < 16 ; i++)
{
if(MappedPens[0][i] == Pen)
return(i);
}
}
/* GetScreenWidth(struct Window *Window):
*
* Query the current screen width.
*/
LONG __regargs
GetScreenWidth(struct Window *Window)
{
if(Window)
{
if(Window -> Width > ScreenWidth || Window -> LeftEdge < -Window -> WScreen -> LeftEdge || Window -> LeftEdge + Window -> WScreen -> LeftEdge + Window -> Width > ScreenWidth)
return(ScreenWidth);
else
return(Window -> Width - (Window -> BorderLeft + Window -> BorderRight));
}
else
return(ScreenWidth);
}
/* GetScreenHeight(struct Window *Window):
*
* Query the current screen height.
*/
LONG __regargs
GetScreenHeight(struct Window *Window)
{
if(Window)
{
if(Window -> Height > ScreenHeight || Window -> TopEdge < -Window -> WScreen -> TopEdge || Window -> TopEdge + Window -> WScreen -> TopEdge + Window -> Height > ScreenHeight)
return(ScreenHeight);
else
return(Window -> Height - (Window -> BorderTop + Window -> BorderBottom));
}
else
return(ScreenHeight);
}
/* GetLeft(struct Screen *Screen):
*
* Get the screen left edge.
*/
STATIC LONG __regargs
GetLeft(struct Screen *Screen)
{
if(Screen -> LeftEdge >= 0)
return(0);
else
return(-Screen -> LeftEdge);
}
/* GetScreenLeft(struct Window *Window):
*
* Query the current screen left edge.
*/
LONG __regargs
GetScreenLeft(struct Window *Window)
{
if(Window)
{
if(Window -> Width > ScreenWidth || Window -> LeftEdge < -Window -> WScreen -> LeftEdge || Window -> LeftEdge + Window -> WScreen -> LeftEdge + Window -> Width > ScreenWidth)
return(GetLeft(Window -> WScreen));
else
return(Window -> LeftEdge + Window -> BorderLeft);
}
else
return(GetLeft(DefaultPubScreen ? DefaultPubScreen : SharedScreen));
}
/* GetTop(struct Screen *Screen):
*
* Get the screen top edge.
*/
STATIC LONG __regargs
GetTop(struct Screen *Screen)
{
if(Screen -> TopEdge >= 0)
return(0);
else
return(-Screen -> TopEdge);
}
/* GetScreenTop(struct Window *Window):
*
* Query the current screen top edge.
*/
LONG __regargs
GetScreenTop(struct Window *Window)
{
if(Window)
{
if(Window -> Height > ScreenHeight || Window -> TopEdge < -Window -> WScreen -> TopEdge || Window -> TopEdge + Window -> WScreen -> TopEdge + Window -> Height > ScreenHeight)
return(GetTop(Window -> WScreen));
else
return(Window -> TopEdge + Window -> BorderTop);
}
else
return(GetTop(DefaultPubScreen ? DefaultPubScreen : SharedScreen));
}
/* OldGetAPen(struct RastPort *RPort):
*
* Query the current primary rendering colour (old style).
*/
ULONG
OldGetAPen(struct RastPort *RPort)
{
return((ULONG)RPort -> FgPen);
}
/* OldGetBPen(struct RastPort *RPort):
*
* Query the current seconary rendering colour (old style).
*/
ULONG
OldGetBPen(struct RastPort *RPort)
{
return((ULONG)RPort -> BgPen);
}
/* OldGetDrMd(struct RastPort *RPort):
*
* Query the current drawing mode (old style).
*/
ULONG
OldGetDrMd(struct RastPort *RPort)
{
return((ULONG)RPort -> DrawMode);
}
/* OldSetWrMsk(struct RastPort *RPort,ULONG Mask):
*
* Set the rendering plane mask (old style).
*/
ULONG
OldSetWrMsk(struct RastPort *RPort,ULONG Mask)
{
RPort -> Mask = Mask;
return((ULONG)1);
}
/* NewGetAPen(struct RastPort *RPort):
*
* Query the current primary rendering colour (new style).
*/
ULONG
NewGetAPen(struct RastPort *RPort)
{
return(GetAPen(RPort));
}
/* NewGetBPen(struct RastPort *RPort):
*
* Query the current seconary rendering colour (new style).
*/
ULONG
NewGetBPen(struct RastPort *RPort)
{
return(GetBPen(RPort));
}
/* NewGetDrMd(struct RastPort *RPort):
*
* Query the current drawing mode (new style).
*/
ULONG
NewGetDrMd(struct RastPort *RPort)
{
return(GetDrMd(RPort));
}
/* NewSetWrMsk(struct RastPort *RPort,ULONG Mask):
*
* Set the rendering plane mask (new style).
*/
ULONG
NewSetWrMsk(struct RastPort *RPort,ULONG Mask)
{
return(SetWriteMask(RPort,Mask));
}
/* SetWait(struct Window *Window):
*
* Set the busy wait mouse pointer.
*/
VOID __regargs
SetWait(struct Window *Window)
{
if(Kick30)
{
SetWindowPointer(Window,
WA_BusyPointer, TRUE,
WA_PointerDelay, TRUE,
TAG_DONE);
}
else
SetPointer(Window,Stopwatch,16,16,-6,0);
}
/* ClrWait(struct Window *Window):
*
* Remove the busy wait mouse pointer.
*/
VOID __regargs
ClrWait(struct Window *Window)
{
if(Kick30)
SetWindowPointer(Window,TAG_DONE);
else
ClearPointer(Window);
}
/* GetModeName(ULONG Mode):
*
* Get the name of a display mode.
*/
STRPTR __regargs
GetModeName(ULONG Mode)
{
STATIC UBYTE __far Buffer[DISPLAYNAMELEN + 1];
struct NameInfo NameInfo;
if(GetDisplayInfoData(NULL,(APTR)&NameInfo,sizeof(struct NameInfo),DTAG_NAME,Mode))
strcpy(Buffer,NameInfo . Name);
else
{
struct DimensionInfo DimensionInfo;
if(GetDisplayInfoData(NULL,(APTR)&DimensionInfo,sizeof(struct DimensionInfo),DTAG_DIMS,Mode))
{
STRPTR MonitorName;
switch(Mode & MONITOR_ID_MASK)
{
case NTSC_MONITOR_ID:
MonitorName = "NTSC: ";
break;
case PAL_MONITOR_ID:
MonitorName = "PAL: ";
break;
case VGA_MONITOR_ID:
MonitorName = "VGA: ";
break;
case A2024_MONITOR_ID:
MonitorName = "A2024: ";
break;
default:
MonitorName = "";
break;
}
SPrintf(Buffer,"%s%ld × %ld",MonitorName,DimensionInfo . TxtOScan . MaxX - DimensionInfo . TxtOScan . MinX + 1,DimensionInfo . TxtOScan . MaxY - DimensionInfo . TxtOScan . MinY + 1);
}
else
strcpy(Buffer,LocaleString(MSG_SCREENPANEL_UNKNOWN_TXT));
}
return(Buffer);
}
/* ModeOkay(ULONG ID):
*
* Checks whether a display mode ID will do for deep
* screen bitmaps.
*/
BYTE __regargs
ModeOkay(ULONG ID)
{
struct DimensionInfo DimensionInfo;
if(GetDisplayInfoData(NULL,(APTR)&DimensionInfo,sizeof(struct DimensionInfo),DTAG_DIMS,ID))
{
if(DimensionInfo . MaxDepth >= 4)
return(TRUE);
}
return(FALSE);
}
/* SetClipMenu(BYTE Mode):
*
* Enable/disable the copy/clear selection menu items.
*/
VOID __regargs
SetClipMenu(BYTE Mode)
{
if(Mode && RasterEnabled)
{
OnItem(MEN_COPY);
OnItem(MEN_CLEAR);
}
else
{
OffItem(MEN_COPY);
OffItem(MEN_CLEAR);
}
}
/* SetRedialMenu():
*
* Make the `redial' menu item available or make it
* unavailable.
*/
VOID
SetRedialMenu()
{
BYTE Mode;
if(DialList)
{
if(DialList -> lh_Head -> ln_Succ)
Mode = TRUE;
else
Mode = FALSE;
}
else
Mode = FALSE;
if(Mode && DialItemsAvailable)
OnItem(MEN_REDIAL);
else
OffItem(MEN_REDIAL);
}
/* SetDialMenu(BYTE Mode):
*
* Block or enable the dialing menu.
*/
VOID __regargs
SetDialMenu(BYTE Mode)
{
if(Window && Menu)
{
if(Mode)
{
if(DialList)
{
if(DialList -> lh_Head -> ln_Succ)
OnItem(MEN_REDIAL);
else
OffItem(MEN_REDIAL);
}
else
OffItem(MEN_REDIAL);
OnItem(MEN_DIAL_NUMBER);
}
else
{
OffItem(MEN_REDIAL);
OffItem(MEN_DIAL_NUMBER);
}
DialItemsAvailable = Mode;
}
}
/* SetTransferMenu(BYTE Mode):
*
* Block or enable the transfer menu.
*/
VOID __regargs
SetTransferMenu(BYTE Mode)
{
if(Window && Menu)
{
if(Mode)
{
ULONG i;
for(i = MEN_UPLOAD_ASCII ; i <= MEN_DOWNLOAD_BINARY ; i++)
OnItem(i);
OnItem(MEN_TRANSFER);
}
else
{
if(!Config -> TransferConfig -> ASCIIUploadLibrary[0])
OffItem(MEN_UPLOAD_ASCII);
else
OnItem(MEN_UPLOAD_ASCII);
if(!Config -> TransferConfig -> ASCIIDownloadLibrary[0])
OffItem(MEN_DOWNLOAD_ASCII);
else
OnItem(MEN_DOWNLOAD_ASCII);
if(!Config -> TransferConfig -> TextUploadLibrary[0])
{
OffItem(MEN_UPLOAD_TEXT);
OffItem(MEN_EDIT_AND_UPLOAD_TEXT);
}
else
{
OnItem(MEN_UPLOAD_TEXT);
OnItem(MEN_EDIT_AND_UPLOAD_TEXT);
}
if(!Config -> TransferConfig -> TextDownloadLibrary[0])
OffItem(MEN_DOWNLOAD_TEXT);
else
OnItem(MEN_DOWNLOAD_TEXT);
if(!Config -> TransferConfig -> BinaryUploadLibrary[0])
OffItem(MEN_UPLOAD_BINARY);
else
OnItem(MEN_UPLOAD_BINARY);
if(!Config -> TransferConfig -> BinaryDownloadLibrary[0])
OffItem(MEN_DOWNLOAD_BINARY);
else
OnItem(MEN_DOWNLOAD_BINARY);
OffItem(MEN_TRANSFER);
}
}
}
/* SetRasterMenu(BYTE Mode):
*
* Block or enable the menu entries associated with
* functions to access the screen raster.
*/
VOID __regargs
SetRasterMenu(BYTE Mode)
{
if(Window && Menu)
{
if(Mode)
{
OnItem(MEN_SAVE_AS_TEXT);
OnItem(MEN_PRINT_SCREEN);
}
else
{
OffItem(MEN_SAVE_AS_TEXT);
OffItem(MEN_PRINT_SCREEN);
}
}
}
/* PickFont(struct Window *Window,STRPTR Name,WORD *Points,BYTE MonoSpaced):
*
* Pick a font using asl.library
*/
BYTE __regargs
PickFont(struct Window *Window,STRPTR Name,WORD *Points,BYTE MonoSpaced)
{
struct FontRequester *Requester;
BYTE Result = FALSE;
LONG Left = 0,
Top = 0,
Width = 0,
Height = 0;
GetWindowInfo(WINDOW_FONT,&Left,&Top,&Width,&Height,Window -> Width / 2,Window -> Height / 2);
if(Requester = (struct FontRequester *)AllocAslRequestTags(ASL_FontRequest,
ASL_Window, Window,
ASL_LeftEdge, Left,
ASL_TopEdge, Top,
ASL_Width, Width,
ASL_Height, Height,
MonoSpaced ? ASL_FuncFlags : TAG_IGNORE, FONF_FIXEDWIDTH,
TAG_DONE))
{
if(AslRequestTags(Requester,
ASL_FontName, Name,
ASL_FontHeight, *Points,
TAG_DONE))
{
PutWindowInfo(WINDOW_FONT,Requester -> fo_LeftEdge,Requester -> fo_TopEdge,Requester -> fo_Width,Requester -> fo_Height);
strcpy(Name,Requester -> fo_Attr . ta_Name);
*Points = Requester -> fo_Attr . ta_YSize;
Result = TRUE;
}
FreeAslRequest(Requester);
}
return(Result);
}
/* ExtractString():
*
* Extracts a string from a list separated by `|' characters.
*/
STRPTR __regargs
ExtractString(STRPTR String,STRPTR Destination,BYTE ReturnEnd)
{
STRPTR OldString;
if(ReturnEnd)
OldString = NULL;
else
OldString = String;
while(*String)
{
if(*String == '|')
{
*Destination = 0;
String++;
if(*String)
return(String);
else
return(OldString);
}
else
*Destination++ = *String++;
}
*Destination = 0;
return(OldString);
}
/* GetListSize(struct List *List):
*
* Determine the number of entries in a list.
*/
LONG __regargs
GetListSize(struct List *List)
{
struct Node *Node = List -> lh_Head;
LONG i = 0;
while(Node -> ln_Succ)
{
i++;
Node = Node -> ln_Succ;
}
return(i);
}
/* GetListNode(LONG Offset,struct List *List):
*
* Return the n-th Node entry in a standard exec list.
*/
struct Node * __regargs
GetListNode(LONG Offset,struct List *List)
{
struct Node *Node;
LONG i;
Node = List -> lh_Head;
for(i = 0 ; i < Offset ; i++)
{
if(!Node -> ln_Succ -> ln_Succ)
return(NULL);
Node = Node -> ln_Succ;
}
return(Node);
}
/* CreateNode(STRPTR Name):
*
* Put a name string into a list node.
*/
struct Node * __regargs
CreateNode(STRPTR Name)
{
struct Node *Node;
if(Node = (struct Node *)AllocVecPooled(sizeof(struct Node) + strlen(Name) + 1,MEMF_ANY | MEMF_PUBLIC))
{
Node -> ln_Name = (STRPTR)(Node + 1);
strcpy(Node -> ln_Name,Name);
}
return(Node);
}
/* FreeNode(struct Node *Node):
*
* Remove and deallocate a node.
*/
VOID __regargs
FreeNode(struct Node *Node)
{
Remove(Node);
FreeVecPooled(Node);
}
/* FreeList(struct List *List):
*
* Remove all nodes from the list
* and free them on the way.
*/
VOID __regargs
FreeList(struct List *List)
{
struct Node *Node,*NextNode;
Node = List -> lh_Head;
while(NextNode = Node -> ln_Succ)
{
Remove(Node);
FreeNode(Node);
Node = NextNode;
}
}
/* GetNodeOffset(struct Node *Node,struct List *List):
*
* Scan a list for a certain node and return
* its position.
*/
LONG __regargs
GetNodeOffset(struct Node *Node,struct List *List)
{
struct Node *ListNode;
LONG Offset = 0;
ListNode = List -> lh_Head;
while(ListNode -> ln_Succ)
{
if(Node == ListNode)
return(Offset);
else
{
Offset++;
ListNode = ListNode -> ln_Succ;
}
}
return(~0);
}
/* MoveList(struct List *From,struct List *To):
*
* Move the contents of a list to a different list.
*/
VOID __regargs
MoveList(struct List *From,struct List *To)
{
struct Node *Node,*NextNode;
Node = From -> lh_Head;
while(NextNode = Node -> ln_Succ)
{
Remove(Node);
AddTail(To,Node);
Node = NextNode;
}
}
/* LogAction(STRPTR String,...):
*
* Write an action to the default log file.
*/
VOID __stdargs
LogAction(STRPTR String,...)
{
if(Config -> CaptureConfig -> LogActions && Config -> CaptureConfig -> LogFileName[0])
{
UBYTE DummyBuffer[512];
BPTR File;
va_list VarArgs;
/* Build a valid string. */
va_start(VarArgs,String);
VSPrintf(DummyBuffer,String,VarArgs);
va_end(VarArgs);
/* Does the log file already exist? */
if(GetFileSize(Config -> CaptureConfig -> LogFileName))
{
/* It does, let's append the data. */
if(File = Open(Config -> CaptureConfig -> LogFileName,MODE_READWRITE))
{
if(Seek(File,0,OFFSET_END) == -1)
{
Close(File);
File = NULL;
}
}
}
else
{
/* Create a new file. */
if(File = Open(Config -> CaptureConfig -> LogFileName,MODE_NEWFILE))
FPrintf(File,LocaleString(MSG_TERMAUX_DATE_TIME_ACTION_TXT));
}
/* The file is open, build the date/time string and
* write the log action.
*/
if(File)
{
UBYTE DateBuffer[40],
TimeBuffer[40];
struct DateTime DateTime;
DateStamp(&DateTime . dat_Stamp);
DateTime . dat_Format = FORMAT_DOS;
DateTime . dat_Flags = NULL;
DateTime . dat_StrDay = NULL;
DateTime . dat_StrDate = DateBuffer;
DateTime . dat_StrTime = TimeBuffer;
if(DateToStr(&DateTime))
{
StripSpaces(TimeBuffer);
FPrintf(File,"%-9s %8s %s\n",DateBuffer,TimeBuffer,DummyBuffer);
}
/* Done! */
Close(File);
}
}
}
/* FlushMsg(struct Window *Window):
*
* Cancel all pending messages of a window.
*/
VOID __regargs
FlushMsg(struct Window *Window)
{
struct IntuiMessage *Massage;
while(Massage = (struct IntuiMessage *)GetMsg(Window -> UserPort))
ReplyMsg(&Massage -> ExecMessage);
}
/* GetString(STRPTR Prompt,STRPTR Buffer):
*
* Get a string from the user, very much the same as xpr_gets,
* but also including the `Load File' gadget.
*/
BYTE __regargs
GetString(BYTE LoadGadget,BYTE Password,WORD MaxChars,STRPTR Prompt,STRPTR Buffer)
{
enum { GAD_OK=1,GAD_CANCEL,GAD_STRING };
struct LayoutHandle *Handle;
BYTE Success = FALSE;
UBYTE LocalBuffer[256];
if(MaxChars > 255)
{
CopyMem(Buffer,LocalBuffer,255);
LocalBuffer[255] = 0;
MaxChars = 255;
}
else
strcpy(LocalBuffer,Buffer);
if(!Prompt)
Prompt = LocaleString(MSG_TERMXPR_INPUT_REQUIRED_TXT);
if(Handle = LT_CreateHandleTags(Window -> WScreen,
LH_LocaleHook, &LocaleHook,
TAG_DONE))
{
struct Window *PanelWindow;
LT_New(Handle,
LA_Type, VERTICAL_KIND,
TAG_DONE);
{
LT_New(Handle,
LA_Type, VERTICAL_KIND,
LA_LabelText, Prompt,
TAG_DONE);
{
if(Password)
{
LT_New(Handle,
LA_Type, PASSWORD_KIND,
LA_STRPTR, LocalBuffer,
LA_ID, GAD_STRING,
LA_Chars, 40,
GTST_MaxChars, MaxChars,
TAG_DONE);
}
else
{
LT_New(Handle,
LA_Type, STRING_KIND,
LA_STRPTR, LocalBuffer,
LA_ID, GAD_STRING,
LA_Chars, 60,
LAST_Picker, LoadGadget,
TAG_DONE);
}
LT_EndGroup(Handle);
}
LT_New(Handle,
LA_Type,VERTICAL_KIND,
TAG_DONE);
{
LT_New(Handle,
LA_Type, XBAR_KIND,
LAXB_FullSize, TRUE,
TAG_DONE);
LT_EndGroup(Handle);
}
LT_New(Handle,LA_Type,HORIZONTAL_KIND,
LAGR_SameSize, TRUE,
LAGR_Spread, TRUE,
TAG_DONE);
{
LT_New(Handle,
LA_Type, BUTTON_KIND,
LA_LabelID, MSG_TERMXPR_OKAY_GAD,
LA_ID, GAD_OK,
LABT_ReturnKey, TRUE,
LABT_ExtraFat, TRUE,
TAG_DONE);
LT_New(Handle,
LA_Type, BUTTON_KIND,
LA_LabelID, MSG_GLOBAL_CANCEL_GAD,
LA_ID, GAD_CANCEL,
LABT_EscKey, TRUE,
LABT_ExtraFat, TRUE,
TAG_DONE);
LT_EndGroup(Handle);
}
}
if(PanelWindow = LT_Layout(Handle,LocaleString(MSG_GLOBAL_ENTER_TEXT_TXT),NULL,0,0,IDCMP_CLOSEWINDOW,0,
LAWN_HelpHook, &GuideHook,
LAWN_Parent, Window,
WA_DepthGadget, TRUE,
WA_CloseGadget, TRUE,
WA_DragBar, TRUE,
WA_RMBTrap, TRUE,
WA_Activate, TRUE,
TAG_DONE))
{
struct IntuiMessage *Message;
BOOLEAN Done = FALSE;
ULONG MsgClass,
MsgQualifier;
UWORD MsgCode;
struct Gadget *MsgGadget;
LT_Activate(Handle,GAD_STRING);
PushWindow(PanelWindow);
LT_ShowWindow(Handle,TRUE);
do
{
if(Wait(PORTMASK(PanelWindow -> UserPort) | SIG_BREAK) & SIG_BREAK)
break;
while(Message = (struct IntuiMessage *)GT_GetIMsg(PanelWindow -> UserPort))
{
MsgClass = Message -> Class;
MsgQualifier = Message -> Qualifier;
MsgCode = Message -> Code;
MsgGadget = (struct Gadget *)Message -> IAddress;
GT_ReplyIMsg(Message);
LT_HandleInput(Handle,MsgQualifier,&MsgClass,&MsgCode,&MsgGadget);
if(MsgClass == IDCMP_CLOSEWINDOW)
Done = TRUE;
if(MsgClass == IDCMP_GADGETUP)
{
switch(MsgGadget -> GadgetID)
{
case GAD_STRING:
if(MsgCode == '\r')
{
strcpy(Buffer,LocalBuffer);
Success = Done = TRUE;
LT_PressButton(Handle,GAD_OK);
}
break;
case GAD_OK:
strcpy(Buffer,LocalBuffer);
Success = Done = TRUE;
break;
case GAD_CANCEL:
Done = TRUE;
break;
}
}
if(MsgClass == IDCMP_IDCMPUPDATE && MsgGadget -> GadgetID == GAD_STRING)
{
UBYTE DummyBuffer[MAX_FILENAME_LENGTH],
*DummyChar;
struct FileRequester *FileRequest;
LT_LockWindow(PanelWindow);
SplitFileName(LocalBuffer,&DummyChar,DummyBuffer);
if(FileRequest = GetFile(PanelWindow,LocaleString(MSG_TERMAUX_LOAD_FILE_TXT),DummyBuffer,DummyChar,DummyBuffer,NULL,FALSE,FALSE,FALSE,LocaleString(MSG_GLOBAL_SELECT_TXT),TRUE))
{
LT_SetAttributes(Handle,GAD_STRING,GTST_String,DummyBuffer,TAG_DONE);
FreeAslRequest(FileRequest);
}
LT_UnlockWindow(PanelWindow);
}
}
}
while(!Done);
PopWindow();
}
LT_DeleteHandle(Handle);
}
return(Success);
}
/* WakeUp(struct Window *Window,WORD Sound):
*
* Pop a window to the front and alert the user.
*/
VOID __regargs
WakeUp(struct Window *Window,WORD Sound)
{
if(Window)
{
if(Config -> TerminalConfig -> AlertMode == ALERT_SCREEN || Config -> TerminalConfig -> AlertMode == ALERT_BEEP_SCREEN)
{
if(Window -> WScreen -> LeftEdge > 0)
{
if(Window -> WScreen -> TopEdge > 0)
MoveScreen(Window -> WScreen,-Window -> WScreen -> LeftEdge,-Window -> WScreen -> TopEdge);
else
MoveScreen(Window -> WScreen,-Window -> WScreen -> LeftEdge,0);
}
else
{
if(Window -> WScreen -> TopEdge > 0)
MoveScreen(Window -> WScreen,0,-Window -> WScreen -> TopEdge);
}
WindowToFront(Window);
ScreenToFront(Window -> WScreen);
}
}
if(Sound != SOUND_BELL || Config -> TerminalConfig -> AlertMode == ALERT_BEEP || Config -> TerminalConfig -> AlertMode == ALERT_BEEP_SCREEN)
SoundPlay(Sound);
}
/* TaskDestructor(struct DataMsg *Item):
*
* Msg destructor for the routines below.
*/
STATIC VOID __stdargs
TaskDestructor(struct DataMsg *Item)
{
Signal((struct Process *)Item -> Data,SIGBREAKF_CTRL_F);
}
/* AmigaDOSBackgroundServer(VOID):
*
* Background process to handle tool execution.
*/
STATIC VOID __saveds
AmigaDOSBackgroundServer(VOID)
{
BPTR OldCOS,
NewCOS = NULL;
struct DataMsg Msg;
STRPTR Command;
struct Process *Me;
/* Look who we are. */
Me = (struct Process *)SysBase -> ThisTask;
Command = Me -> pr_Task . tc_UserData;
/* Create console output stream, will be closed automagically on exit. */
if(!Me -> pr_COS && Me -> pr_ConsoleTask)
{
if(NewCOS = Open("*",MODE_NEWFILE))
{
OldCOS = Me -> pr_COS;
Me -> pr_COS = NewCOS;
}
}
SystemTags(Command,
SYS_UserShell, TRUE,
TAG_DONE);
FreeVecPooled(Command);
Forbid();
InitMsgItem(&Msg,TaskDestructor);
Msg . Type = DATAMSGTYPE_COMMANDDONE;
Msg . Data = (UBYTE *)Me;
ClrSignal(SIGBREAKF_CTRL_F);
PutMsgItem(SpecialQueue,(struct MsgItem *)&Msg);
Wait(SIGBREAKF_CTRL_F);
if(NewCOS)
{
Me -> pr_COS = OldCOS;
Close(NewCOS);
}
}
/* SendAmigaDOSCommand(STRPTR Name):
*
* Let the current default Shell execute an AmigaDOS
* command. Block until the command has returned.
*/
VOID __regargs
SendAmigaDOSCommand(STRPTR Name)
{
STRPTR NewName;
if(NewName = (STRPTR)AllocVecPooled(strlen(Name) + 1 + 256,MEMF_ANY))
{
struct Process *NewProcess;
BPTR Stream;
STRPTR NewWindowName;
strcpy(NewName,Name);
NewWindowName = NewName + strlen(NewName) + 1;
BlockWindows();
SetQueueDiscard(SpecialQueue,FALSE);
/* Open the output file. */
if(WindowName[0])
{
UBYTE LocalName[MAXPUBSCREENNAME + 1];
if(Window)
{
if(!GetPubScreenName(Window -> WScreen,LocalName))
LocalName[0] = 0;
}
if(LocalName[0])
{
SPrintf(NewWindowName,WindowName,LocalName);
Stream = Open(NewWindowName,MODE_NEWFILE);
}
else
Stream = Open(WindowName,MODE_NEWFILE);
}
else
Stream = NULL;
Forbid();
if(Stream)
{
if(GoodStream(Stream))
{
struct FileHandle *Handle = (struct FileHandle *)BADDR(Stream);
NewProcess = (struct Process *)CreateNewProcTags(
NP_Entry, AmigaDOSBackgroundServer,
NP_Name, "term AmigaDOS Background Process",
NP_Input, Stream,
NP_Output, NULL,
NP_Cli, TRUE,
NP_ConsoleTask, Handle -> fh_Type,
NP_StackSize, 16384,
TAG_END);
}
else
{
NewProcess = (struct Process *)CreateNewProcTags(
NP_Entry, AmigaDOSBackgroundServer,
NP_Name, "term AmigaDOS Background Process",
NP_Output, Stream,
NP_Cli, TRUE,
NP_ConsoleTask, NULL,
NP_StackSize, 16384,
TAG_END);
}
}
else
{
NewProcess = (struct Process *)CreateNewProcTags(
NP_Entry, AmigaDOSBackgroundServer,
NP_Name, "term AmigaDOS Background Process",
NP_Cli, TRUE,
NP_ConsoleTask, NULL,
NP_StackSize, 16384,
TAG_END);
}
/* Did we succeed in creating the process? */
if(NewProcess)
{
CantQuit++;
NewProcess -> pr_Task . tc_UserData = NewName;
Permit();
}
else
{
Permit();
if(Stream)
Close(Stream);
FreeVecPooled(NewName);
BumpWindow(Window);
ReleaseWindows();
}
}
}
/* RexxBackgroundServer():
*
* The background process to handle the rexx
* massaging.
*/
STATIC VOID __saveds
RexxBackgroundServer(VOID)
{
struct MsgPort *RexxPort;
BPTR OldCOS,
NewCOS = NULL;
struct DataMsg Msg;
STRPTR Command;
struct Process *Me;
/* Look who we are. */
Me = (struct Process *)SysBase -> ThisTask;
Command = Me -> pr_Task . tc_UserData;
/* Create console output stream, will be closed automagically on exit. */
if(!Me -> pr_COS && Me -> pr_ConsoleTask)
{
if(NewCOS = Open("*",MODE_NEWFILE))
{
OldCOS = Me -> pr_COS;
Me -> pr_COS = NewCOS;
}
}
if(RexxPort = FindPort(RXSDIR))
{
struct MsgPort __aligned ReplyPort;
struct RexxMsg *RexxMsg;
InitSinglePort(&ReplyPort);
if(RexxMsg = CreateRexxMsg(&ReplyPort,"term",RexxPortName))
{
if(RexxMsg -> rm_Args[0] = CreateArgstring(Command,strlen(Command)))
{
RexxMsg -> rm_Action = RXCOMM;
Forbid();
ClrSignal(SIGF_SINGLE);
PutMsg(RexxPort,(struct Message *)RexxMsg);
WaitPort(&ReplyPort);
GetMsg(&ReplyPort);
Permit();
/* This doesn't look too
* good, does it?
*/
if(RexxMsg -> rm_Result1 && Me -> pr_COS)
Printf(LocaleString(MSG_TERMAUX_COMMAND_HAS_TERMINATED_TXT),Command,RexxMsg -> rm_Result1,RexxMsg -> rm_Result2);
DeleteArgstring(RexxMsg -> rm_Args[0]);
}
DeleteRexxMsg(RexxMsg);
}
}
FreeVecPooled(Command);
Forbid();
InitMsgItem(&Msg,TaskDestructor);
Msg . Type = DATAMSGTYPE_COMMANDDONE;
Msg . Data = (UBYTE *)Me;
ClrSignal(SIGBREAKF_CTRL_F);
PutMsgItem(SpecialQueue,(struct MsgItem *)&Msg);
Wait(SIGBREAKF_CTRL_F);
if(NewCOS)
{
Me -> pr_COS = OldCOS;
Close(NewCOS);
}
}
/* SendARexxCommand(STRPTR Name):
*
* Let the ARexx server execute a command (or a script
* file if necessary) and block until the command
* has returned.
*/
VOID __regargs
SendARexxCommand(STRPTR Name)
{
STRPTR NewName;
if(NewName = (STRPTR)AllocVecPooled(strlen(Name) + 1 + 256,MEMF_ANY))
{
struct Process *NewProcess;
BPTR Stream;
STRPTR NewWindowName;
strcpy(NewName,Name);
NewWindowName = NewName + strlen(NewName) + 1;
BlockWindows();
SetQueueDiscard(SpecialQueue,FALSE);
/* Open the output file. */
if(WindowName[0])
{
UBYTE LocalName[MAXPUBSCREENNAME + 1];
if(Window)
{
if(!GetPubScreenName(Window -> WScreen,LocalName))
LocalName[0] = 0;
}
if(LocalName[0])
{
SPrintf(NewWindowName,WindowName,LocalName);
Stream = Open(NewWindowName,MODE_NEWFILE);
}
else
Stream = Open(WindowName,MODE_NEWFILE);
}
else
Stream = NULL;
Forbid();
/* Create the background process which will
* handle all the messy rexx message sending
* for us.
*/
if(Stream)
{
if(GoodStream(Stream))
{
struct FileHandle *Handle = (struct FileHandle *)BADDR(Stream);
NewProcess = (struct Process *)CreateNewProcTags(
NP_Entry, RexxBackgroundServer,
NP_Name, "term ARexx Background Process",
NP_Input, Stream,
NP_Output, NULL,
NP_Cli, TRUE,
NP_ConsoleTask, Handle -> fh_Type,
NP_StackSize, 16384,
TAG_END);
}
else
{
NewProcess = (struct Process *)CreateNewProcTags(
NP_Entry, RexxBackgroundServer,
NP_Name, "term ARexx Background Process",
NP_Output, Stream,
NP_Cli, TRUE,
NP_ConsoleTask, NULL,
NP_StackSize, 16384,
TAG_END);
}
}
else
{
NewProcess = (struct Process *)CreateNewProcTags(
NP_Entry, RexxBackgroundServer,
NP_Name, "term ARexx Background Process",
NP_Cli, TRUE,
NP_ConsoleTask, NULL,
NP_StackSize, 16384,
TAG_END);
}
/* Did we succeed in creating the process? */
if(NewProcess)
{
CantQuit++;
NewProcess -> pr_Task . tc_UserData = NewName;
Permit();
}
else
{
Permit();
if(Stream)
Close(Stream);
FreeVecPooled(NewName);
BumpWindow(Window);
ReleaseWindows();
}
}
}
/* BlockWindows():
*
* Block the main window and the status window (i.e. disable
* the menu and attach a wait pointer).
*/
VOID
BlockWindows()
{
if(!(BlockNestCount++))
{
LT_LockWindow(Window);
LT_LockWindow(StatusWindow);
LT_LockWindow(FastWindow);
WeAreBlocking = TRUE;
SetQueueDiscard(SpecialQueue,TRUE);
GhostCursor();
}
}
/* ReleaseWindows():
*
* Reenable the menus and clear the wait pointer.
*/
VOID
ReleaseWindows()
{
if(BlockNestCount == 1)
{
LT_UnlockWindow(Window);
LT_UnlockWindow(StatusWindow);
LT_UnlockWindow(FastWindow);
WeAreBlocking = FALSE;
SetQueueDiscard(SpecialQueue,FALSE);
if(Window)
{
Forbid();
if(Window -> Flags & WFLG_WINDOWACTIVE)
NormalCursor();
Permit();
}
}
if(BlockNestCount)
BlockNestCount--;
}
/* LineRead(BPTR File,STRPTR Buffer,LONG MaxChars):
*
* Read a few bytes from a file (à la gets).
*/
LONG __regargs
LineRead(BPTR File,STRPTR Buffer,LONG MaxChars)
{
STATIC UBYTE __far Data[1024];
STATIC LONG ReadIndex = 0,
ReadLen = 0;
if(File)
{
LONG BytesRead = 0,i;
for(i = 0 ; i < MaxChars ; i++)
{
if(ReadIndex >= ReadLen)
{
ReadLen = Read(File,Data,1024);
ReadIndex = 0;
if(ReadLen <= 0)
{
Buffer[i] = 0;
return(BytesRead);
}
}
BytesRead++;
if((Buffer[i] = Data[ReadIndex++]) == '\n')
{
Buffer[i + 1] = 0;
return(BytesRead);
}
}
return(BytesRead);
}
else
ReadIndex = ReadLen = 0;
}
/* GetBaudRate(STRPTR Buffer):
*
* Calculate the baud rate contained in a connect string.
*/
LONG __regargs
GetBaudRate(STRPTR Buffer)
{
LONG Rate,i,j;
for(i = j = 0 ; i < strlen(Buffer) ; i++)
{
if(Buffer[i] == ' ')
continue;
else
{
if(Buffer[i] >= '0' && Buffer[i] <= '9')
SharedBuffer[j++] = Buffer[i];
else
break;
}
}
SharedBuffer[j] = 0;
if(StrToLong(SharedBuffer,&Rate) > 0)
{
if(Rate > 0)
return(Rate);
}
return(0);
}
/* LookForIt(struct MenuItem *Item,ULONG ID):
*
* Auxilary routine for FindThisItem(), scans
* menu item and sub item lists.
*/
STATIC struct MenuItem * __inline
LookForIt(struct MenuItem *Item,ULONG ID)
{
while(Item)
{
if((ULONG)GTMENUITEM_USERDATA(Item) == ID)
return(Item);
else
{
if(Item -> SubItem)
{
register struct MenuItem *TheItem;
if(TheItem = LookForIt(Item -> SubItem,ID))
return(TheItem);
}
Item = Item -> NextItem;
}
}
return(NULL);
}
/* FindThisItem(struct Menu *FirstMenu,ULONG MenuID):
*
* Scan a menu for a menuitem associated with a
* menu ID.
*/
struct MenuItem * __regargs
FindThisItem(struct Menu *FirstMenu,ULONG MenuID)
{
struct MenuItem *Item;
while(FirstMenu)
{
if(Item = LookForIt(FirstMenu -> FirstItem,MenuID))
return(Item);
else
FirstMenu = FirstMenu -> NextMenu;
}
return(NULL);
}
/* GetItem(ULONG MenuID):
*
* Get the checkmark state of a menu item.
*/
BYTE __regargs
GetItem(ULONG MenuID)
{
if(Menu)
{
struct MenuItem *Item;
if(Item = FindThisItem(Menu,MenuID))
{
if(Item -> Flags & CHECKED)
return(TRUE);
}
}
return(FALSE);
}
/* SetItem(ULONG MenuID,BYTE Mode):
*
* Clear or set the checkmark or state of a menu item.
*/
VOID __regargs
SetItem(ULONG MenuID,BYTE Mode)
{
/* Is the global pull-down menu available? */
if(Menu)
{
struct MenuItem *Item;
/* Try to find the menu item and change
* the state of the checkmark.
*/
if(Item = FindThisItem(Menu,MenuID))
{
/* Remove the menu from the windows. */
if(Window)
ClearMenuStrip(Window);
if(StatusWindow)
ClearMenuStrip(StatusWindow);
if(FastWindow)
ClearMenuStrip(FastWindow);
switch(Mode)
{
case SETITEM_SETCHECK:
Item -> Flags |= CHECKED;
break;
case SETITEM_CLRCHECK:
Item -> Flags &= ~CHECKED;
break;
case SETITEM_ON:
Item -> Flags |= ITEMENABLED;
break;
case SETITEM_OFF:
Item -> Flags &= ~ITEMENABLED;
break;
}
/* Reattach the menu to the windows. */
if(Window)
ResetMenuStrip(Window,Menu);
if(StatusWindow)
ResetMenuStrip(StatusWindow,Menu);
if(FastWindow)
ResetMenuStrip(FastWindow,Menu);
}
}
}
/* GetFileSize(STRPTR Name):
*
* Simple routine to return the size of a file in
* bytes.
*/
LONG __regargs
GetFileSize(STRPTR Name)
{
struct FileInfoBlock *FileInfo;
LONG FileSize = 0;
if(FileInfo = (struct FileInfoBlock *)AllocDosObject(DOS_FIB,TAG_DONE))
{
BPTR FileLock;
if(FileLock = Lock(Name,ACCESS_READ))
{
if(Examine(FileLock,FileInfo))
{
if(FileInfo -> fib_DirEntryType < 0)
FileSize = FileInfo -> fib_Size;
}
UnLock(FileLock);
}
FreeDosObject(DOS_FIB,FileInfo);
}
return(FileSize);
}
/* GetFile(STRPTR Title,STRPTR Directory,STRPTR Name,STRPTR Buffer,STRPTR Pattern,BYTE SaveFlag,BYTE MultiSelect):
*
* Call the asl.library file requester to select a single or
* a couple of files.
*/
struct FileRequester * __regargs
GetFile(struct Window *Parent,STRPTR Title,STRPTR Directory,STRPTR Name,STRPTR Buffer,STRPTR Pattern,BYTE SaveFlag,BYTE MultiSelect,BYTE DirsOnly,STRPTR OKText,BYTE AskWrite)
{
STATIC UBYTE __far DirBuffer[MAX_FILENAME_LENGTH],
PatternBuffer[60];
struct FileRequester *AslFileRequest;
BYTE Result = FALSE,
DefaultPattern = FALSE;
LONG Flags,ExtFlags = 0;
WORD i,j;
UBYTE OtherTitle[60];
LONG Left = 0,
Top = 0,
Width = 0,
Height = 0;
if(!Parent)
Parent = Window;
for(i = j = 0 ; i < strlen(Title) ; i++)
{
if(Title[i] != '_')
OtherTitle[j++] = Title[i];
}
OtherTitle[j] = 0;
Title = OtherTitle;
if(DirsOnly)
{
ExtFlags |= FIL1F_NOFILES;
if(Pattern)
ExtFlags |= FIL1F_MATCHDIRS;
}
GetWindowInfo(WINDOW_FILE,&Left,&Top,&Width,&Height,Window -> Width / 2,Window -> Height / 2);
/* Empty directory string? Revert to the last directory
* name.
*/
Forbid();
if(!Directory[0])
{
if(!DirBuffer[0])
{
UBYTE LocalBuffer[MAX_FILENAME_LENGTH];
if(!GetCurrentDirName(LocalBuffer,MAX_FILENAME_LENGTH))
LocalBuffer[0] = 0;
if(!DirBuffer[0])
strcpy(DirBuffer,LocalBuffer);
}
Directory = DirBuffer;
}
/* If a wildcard pattern is required, add a gadget
* to display it.
*/
if(Pattern)
{
Flags = FILF_PATGAD;
if(!Pattern[0])
{
DefaultPattern = TRUE;
if(PatternBuffer[0])
Pattern = PatternBuffer;
else
Pattern = "#?";
}
else
{
if(!Stricmp(Pattern,"#?") || !Stricmp(Pattern,PatternBuffer))
{
DefaultPattern = TRUE;
Pattern = PatternBuffer;
}
}
}
else
{
Flags = 0;
Pattern = "#?";
}
Permit();
/* Set the save flag if we are about to save something. */
if(SaveFlag)
Flags |= FILF_SAVE;
/* Set the multiselect bit if multiple files are
* to be selected (e.g. for batch file upload).
*/
if(MultiSelect)
Flags |= FILF_MULTISELECT;
/* Provide a standard `Ok' text if none
* specified.
*/
if(!OKText)
OKText = (SaveFlag ? LocaleString(MSG_GLOBAL_SAVE_TXT) : LocaleString(MSG_GLOBAL_OPEN_TXT));
/* Allocate the asl.library directory requester
* and display it.
*/
if(AslFileRequest = (struct FileRequester *)AllocAslRequestTags(ASL_FileRequest,
ASL_Window, Parent,
ASL_File, Name,
ASL_Dir, Directory,
Title ? ASL_Hail : TAG_IGNORE, Title,
ASL_FuncFlags, Flags | FILF_NEWIDCMP,
ASL_Pattern, Pattern,
ASL_OKText, OKText,
ASL_ExtFlags1, ExtFlags,
ASLFR_TextAttr, &UserFont,
ASL_LeftEdge, Left,
ASL_TopEdge, Top,
ASL_Width, Width,
ASL_Height, Height,
TAG_DONE))
{
if(AslRequestTags(AslFileRequest,TAG_DONE))
{
PutWindowInfo(WINDOW_FILE,AslFileRequest -> rf_LeftEdge,AslFileRequest -> rf_TopEdge,AslFileRequest -> rf_Width,AslFileRequest -> rf_Height);
if(!DirsOnly)
{
STRPTR FileName;
if(AslFileRequest -> rf_NumArgs > 1 && AslFileRequest -> rf_ArgList)
FileName = AslFileRequest -> rf_ArgList -> wa_Name;
else
FileName = AslFileRequest -> rf_File;
/* Do we have a valid file name? */
if(FileName)
{
/* Build a legal path/file string. */
strcpy(Buffer,AslFileRequest -> rf_Dir);
AddPart((STRPTR)Buffer,FileName,MAX_FILENAME_LENGTH);
Result = TRUE;
Forbid();
strcpy(DirBuffer,AslFileRequest -> rf_Dir);
Permit();
}
}
else
{
if(AslFileRequest -> rf_Dir[0])
{
strcpy(Buffer,AslFileRequest -> rf_Dir);
Result = TRUE;
Forbid();
strcpy(DirBuffer,AslFileRequest -> rf_Dir);
Permit();
}
}
}
}
/* We didn't get a file, no need to keep the
* file requester.
*/
if(!Result && AslFileRequest)
{
FreeAslRequest(AslFileRequest);
return(NULL);
}
else
{
if(SaveFlag && AskWrite)
{
if(GetFileSize(Buffer))
{
if(!MyEasyRequest(Parent,LocaleString(MSG_GLOBAL_FILE_ALREADY_EXISTS_OVERWRITE_TXT),LocaleString(MSG_GLOBAL_REPLACE_CANCEL_TXT),FilePart(Buffer)))
{
FreeAslRequest(AslFileRequest);
return(NULL);
}
}
}
Forbid();
if(DefaultPattern)
strcpy(PatternBuffer,AslFileRequest -> rf_Pat);
Permit();
return(AslFileRequest);
}
}
/* MyEasyRequest(struct Window *Window,STRPTR Text,STRPTR Gadgets,...):
*
* Really quite simple varargs version of Intuition's
* EasyRequest requester.
*/
WORD __stdargs
MyEasyRequest(struct Window *Window,STRPTR Text,STRPTR Gadgets,...)
{
struct EasyStruct Easy;
WORD Result;
va_list VarArgs;
/* Standard data. */
Easy . es_StructSize = sizeof(struct EasyStruct);
Easy . es_Flags = NULL;
Easy . es_Title = LocaleString(MSG_TERMAUX_TERM_REQUEST_TXT);
Easy . es_TextFormat = Text;
Easy . es_GadgetFormat = Gadgets;
/* Use the argument array to build the
* requester and display it.
*/
va_start(VarArgs,Gadgets);
Result = EasyRequestArgs(Window,&Easy,NULL,VarArgs);
va_end(VarArgs);
return(Result);
}
/* CloseWindowSafely(struct Window *Window):
*
* Close a window freeing all messages pending at
* its user port (taken from example source code
* published once upon a time in Amiga Mail).
*/
VOID __regargs
CloseWindowSafely(struct Window *Window)
{
struct IntuiMessage *IntuiMessage;
struct Node *Successor;
Forbid();
IntuiMessage = (struct IntuiMessage *)Window -> UserPort -> mp_MsgList . lh_Head;
while(Successor = IntuiMessage -> ExecMessage . mn_Node . ln_Succ)
{
if(IntuiMessage -> IDCMPWindow == Window)
{
Remove(IntuiMessage);
ReplyMsg((struct Message *)IntuiMessage);
}
IntuiMessage = (struct IntuiMessage *)Successor;
}
Window -> UserPort = NULL;
ModifyIDCMP(Window,NULL);
Permit();
LT_DeleteWindowLock(Window);
CloseWindow(Window);
}
/* WaitTime(LONG Secs,LONG Micros):
*
* Wait a given period of time.
*/
VOID __regargs
WaitTime(LONG Secs,LONG Micros)
{
TimeRequest -> tr_node . io_Command = TR_ADDREQUEST;
TimeRequest -> tr_time . tv_secs = Secs;
TimeRequest -> tr_time . tv_micro = Micros;
DoIO(TimeRequest);
}
/* StopTime():
*
* Stop the running timer.
*/
VOID
StopTime()
{
if(TimerRunning)
{
if(!CheckIO(TimeRequest))
AbortIO(TimeRequest);
WaitIO(TimeRequest);
}
}
/* StartTime(LONG Secs,LONG Micros):
*
* Start the timer asynchronously.
*/
VOID __regargs
StartTime(LONG Secs,LONG Micros)
{
StopTime();
TimeRequest -> tr_node . io_Command = TR_ADDREQUEST;
TimeRequest -> tr_time . tv_secs = Secs;
TimeRequest -> tr_time . tv_micro = Micros;
ClrSignal(SIG_TIMER);
SendIO(TimeRequest);
TimerRunning = TRUE;
}
/* GetEnvDOS(STRPTR Name,STRPTR Buffer):
*
* Get the contents of a vanilla AmigaDOS environment
* variable.
*/
STRPTR __regargs
GetEnvDOS(STRPTR Name,STRPTR Buffer)
{
LONG Size;
BPTR File,SomeLock;
Buffer[0] = 0;
/* Is ENV: present? */
if(SomeLock = Lock("Env:",ACCESS_READ))
{
UBYTE SomeBuffer[MAX_FILENAME_LENGTH];
UnLock(SomeLock);
strcpy(SomeBuffer,"Env:");
strcat(SomeBuffer,Name);
/* Open the file. */
if(File = Open(SomeBuffer,MODE_OLDFILE))
{
/* Read the contents. */
Size = Read(File,Buffer,256);
Close(File);
if(Size > 0)
{
Buffer[Size] = 0;
return(Buffer);
}
}
}
return(NULL);
}
/* SetEnvDOS(STRPTR Name,STRPTR Value):
*
* Set the contents of a vanilla AmigaDOS environment
* variable.
*/
BYTE __regargs
SetEnvDOS(STRPTR Name,STRPTR Value)
{
UBYTE Buffer[MAX_FILENAME_LENGTH],*Destination;
LONG Length;
BPTR File,FileLock;
BYTE Success = TRUE;
WORD i;
for(i = 0 ; i < 2 ; i++)
{
if(i)
Destination = "EnvArc:";
else
Destination = "Env:";
/* Is ENV:/ENVARC: present? */
if(FileLock = Lock(Destination,ACCESS_READ))
{
UnLock(FileLock);
strcpy(Buffer,Destination);
strcat(Buffer,Name);
/* There already is a variable of that
* name in the environment storage
* directory.
*/
if(FileLock = Lock(Buffer,ACCESS_WRITE))
{
UnLock(FileLock);
/* Delete the variable. */
if(!DeleteFile(Buffer))
{
Success = FALSE;
continue;
}
}
/* Set the new variable. */
if(Length = strlen(Value))
{
if(File = Open(Buffer,MODE_NEWFILE))
{
if(Write(File,Value,Length) != Length)
{
Close(File);
DeleteFile(Buffer);
Success = FALSE;
}
else
{
Close(File);
AddProtection(Buffer,FIBF_EXECUTE);
}
}
else
Success = FALSE;
}
}
else
Success = FALSE;
}
return(Success);
}
/* BumpWindow(struct Window *SomeWindow):
*
* Bring a window to the front (and shift the screen
* back to its initial position).
*/
VOID __regargs
BumpWindow(struct Window *SomeWindow)
{
if(SomeWindow)
{
if(SomeWindow -> WScreen -> LeftEdge > 0)
{
if(SomeWindow -> WScreen -> TopEdge > 0)
MoveScreen(SomeWindow -> WScreen,-SomeWindow -> WScreen -> LeftEdge,-SomeWindow -> WScreen -> TopEdge);
else
MoveScreen(SomeWindow -> WScreen,-SomeWindow -> WScreen -> LeftEdge,0);
}
else
{
if(SomeWindow -> WScreen -> TopEdge > 0)
MoveScreen(SomeWindow -> WScreen,0,-SomeWindow -> WScreen -> TopEdge);
}
ScreenToFront(SomeWindow -> WScreen);
ActivateWindow(SomeWindow);
}
}
/* PushWindow(struct Window *Window):
*
* Push/PopWindow implement a single lifo window stack
* which always updates the window to activate when
* LSHIFT+RSHIFT+RETURN is pressed. This routine will
* push a window on the stack.
*/
VOID __regargs
PushWindow(struct Window *Window)
{
if(WindowStackPtr < 5)
{
WindowStack[WindowStackPtr++] = Window;
TopWindow = Window;
}
}
/* PopWindow():
*
* Remove topmost window from window stack.
*/
VOID
PopWindow()
{
if(WindowStackPtr > 0)
{
WindowStackPtr--;
if(WindowStackPtr)
TopWindow = WindowStack[WindowStackPtr - 1];
else
TopWindow = Window;
}
}
/* LoadMacros(STRPTR Name,struct MacroKeys *Keys):
*
* Load the keyboard macros from a file.
*/
BYTE __regargs
LoadMacros(STRPTR Name,struct MacroKeys *Keys)
{
struct IFFHandle *Handle;
BYTE Success = FALSE;
struct StoredProperty *Prop;
struct TermInfo *TermInfo;
LONG Error;
if(Handle = AllocIFF())
{
if(Handle -> iff_Stream = Open(Name,MODE_OLDFILE))
{
InitIFFasDOS(Handle);
if(!(Error = OpenIFF(Handle,IFFF_READ)))
{
/* Collect version number ID if
* available.
*/
if(!(Error = PropChunks(Handle,(LONG *)VersionProps,1)))
{
/* The following line tells iffparse to stop at the
* very beginning of a `Type' chunk contained in a
* `TERM' FORM chunk.
*/
if(!(Error = StopChunk(Handle,ID_TERM,ID_KEYS)))
{
/* Parse the file... */
if(!ParseIFF(Handle,IFFPARSE_SCAN))
{
/* Did we get a version ID? */
if(Prop = FindProp(Handle,ID_TERM,ID_VERS))
{
TermInfo = (struct TermInfo *)Prop -> sp_Data;
/* Is it the file format we are able
* to read?
*/
if((TermInfo -> Version > TermVersion) || (TermInfo -> Version == TermVersion && TermInfo -> Revision > TermRevision) || (TermInfo -> Version == 1 && TermInfo -> Revision < 6))
{
/* Probably an older revision. */
if(TermInfo -> Version == 1 && TermInfo -> Revision < 6)
{
memset(Keys,0,sizeof(struct MacroKeys));
if(ReadChunkBytes(Handle,Keys,10 * 256) == 10 * 256)
Success = TRUE;
else
Error = IoErr();
}
else
Error = ERR_OUTDATED;
}
else
{
/* The file read pointer is positioned
* just in front of the first data
* to be read, so let's don't disappoint
* iffparse and read it.
*/
if(ReadChunkBytes(Handle,Keys,sizeof(struct MacroKeys)) == sizeof(struct MacroKeys))
Success = TRUE;
else
Error = IoErr();
}
}
else
{
/* File was created by WriteIFFData previous
* to revision 1.4.
*/
memset(Keys,0,sizeof(struct MacroKeys));
if(ReadChunkBytes(Handle,Keys,10 * 256) == 10 * 256)
Success = TRUE;
else
Error = IoErr();
}
}
}
}
CloseIFF(Handle);
}
Close(Handle -> iff_Stream);
}
else
Error = IoErr();
FreeIFF(Handle);
}
else
Error = ERR_NO_MEM;
if(Error)
SetIoErr(Error);
return(Success);
}
/* WriteIFFData(STRPTR Name,APTR Data,LONG Size,ULONG Type):
*
* Write data to an IFF file (via iffparse.library).
*/
BYTE __regargs
WriteIFFData(STRPTR Name,APTR Data,LONG Size,ULONG Type)
{
struct IFFHandle *Handle;
BYTE Success = FALSE;
LONG Error;
/* Allocate a handle. */
if(Handle = AllocIFF())
{
/* Open an output stream. */
if(Handle -> iff_Stream = Open(Name,MODE_NEWFILE))
{
/* Tell iffparse that this is
* a DOS handle.
*/
InitIFFasDOS(Handle);
/* Open the handle for writing. */
if(!(Error = OpenIFF(Handle,IFFF_WRITE)))
{
/* Push outmost chunk onto stack. */
if(!(Error = PushChunk(Handle,ID_TERM,ID_FORM,IFFSIZE_UNKNOWN)))
{
/* Add a version identifier. */
if(!(Error = PushChunk(Handle,0,ID_VERS,IFFSIZE_UNKNOWN)))
{
struct TermInfo TermInfo;
TermInfo . Version = TermVersion;
TermInfo . Revision = TermRevision;
/* Write the version data. */
if(WriteChunkBytes(Handle,&TermInfo,sizeof(struct TermInfo)) == sizeof(struct TermInfo))
{
/* Pop the version chunk, i.e. write it to the file. */
if(Error = PopChunk(Handle))
Success = FALSE;
else
{
/* Push the real data chunk on the stack. */
if(!(Error = PushChunk(Handle,0,Type,IFFSIZE_UNKNOWN)))
{
/* Write the data. */
if(WriteChunkBytes(Handle,Data,Size) == Size)
Success = TRUE;
else
Error = IoErr();
/* Pop the data chunk. */
if(Success)
{
if(Error = PopChunk(Handle))
Success = FALSE;
}
}
else
Success = FALSE;
}
}
else
{
Error = IoErr();
Success = FALSE;
}
}
/* Seems that we're done, now try to pop the FORM chunk
* and return.
*/
if(Success)
{
if(Error = PopChunk(Handle))
Success = FALSE;
}
}
/* Close the handle (flush any pending data). */
CloseIFF(Handle);
}
/* Close the DOS handle itself. */
Close(Handle -> iff_Stream);
}
else
Error = IoErr();
/* And free the IFF handle. */
FreeIFF(Handle);
}
else
Error = ERR_NO_MEM;
if(Success)
AddProtection(Name,FIBF_EXECUTE);
if(Error)
SetIoErr(Error);
return(Success);
}
/* ReadIFFData(STRPTR Name,APTR Data,LONG Size,ULONG Type):
*
* Read data from a `TERM' FORM chunk contained in an IFF file.
*/
BYTE __regargs
ReadIFFData(STRPTR Name,APTR Data,LONG Size,ULONG Type)
{
struct IFFHandle *Handle;
BYTE Success = FALSE;
struct StoredProperty *Prop;
struct TermInfo *TermInfo;
LONG Error = 0;
if(Handle = AllocIFF())
{
if(Handle -> iff_Stream = Open(Name,MODE_OLDFILE))
{
InitIFFasDOS(Handle);
if(!(Error = OpenIFF(Handle,IFFF_READ)))
{
/* Collect version number ID if
* available.
*/
if(!(Error = PropChunks(Handle,(LONG *)VersionProps,1)))
{
/* The following line tells iffparse to stop at the
* very beginning of a `Type' chunk contained in a
* `TERM' FORM chunk.
*/
if(!(Error = StopChunk(Handle,ID_TERM,Type)))
{
/* Parse the file... */
if(!ParseIFF(Handle,IFFPARSE_SCAN))
{
/* Did we get a version ID? */
if(Prop = FindProp(Handle,ID_TERM,ID_VERS))
{
TermInfo = (struct TermInfo *)Prop -> sp_Data;
/* Is it the file format we are able
* to read?
*/
if((TermInfo -> Version > TermVersion) || (TermInfo -> Version == TermVersion && TermInfo -> Revision > TermRevision) || (TermInfo -> Version == 1 && TermInfo -> Revision < 6))
{
Error = ERR_OUTDATED;
Success = FALSE;
}
else
{
struct ContextNode *Chunk = CurrentChunk(Handle);
if(Chunk -> cn_Size < Size)
Size = Chunk -> cn_Size;
/* The file read pointer is positioned
* just in front of the first data
* to be read, so let's don't disappoint
* iffparse and read it.
*/
if(ReadChunkBytes(Handle,Data,Size) == Size)
Success = TRUE;
else
Error = IoErr();
}
}
}
}
}
CloseIFF(Handle);
}
Close(Handle -> iff_Stream);
}
else
Error = IoErr();
FreeIFF(Handle);
}
if(Error)
SetIoErr(Error);
return(Success);
}
/* SplitFileName():
*
* Split a full file name into a file and a drawer name.
*/
VOID __regargs
SplitFileName(STRPTR FullName,STRPTR *FileName,STRPTR DrawerName)
{
if(FilePart(FullName) == FullName)
{
*DrawerName = 0;
*FileName = FullName;
}
else
{
STRPTR Dummy;
strcpy(DrawerName,FullName);
Dummy = PathPart(DrawerName);
*Dummy = 0;
*FileName = FilePart(FullName);
}
}
/* CreateList():
*
* Create a small, empty list.
*/
struct List *
CreateList()
{
struct List *List = (struct List *)AllocVecPooled(sizeof(struct MinList),MEMF_ANY);
if(List)
NewList(List);
return(List);
}
/* DeleteList():
*
* Free the contents of a list and the list itself.
*/
VOID __regargs
DeleteList(struct List *List)
{
if(List)
{
struct Node *Node,
*Next;
for(Node = List -> lh_Head ; Next = Node -> ln_Succ ; Node = Next)
FreeVecPooled(Node);
FreeVecPooled(List);
}
}
/* BackfillRoutine():
*
* Window layer backfill routine.
*/
ULONG __asm __saveds
BackfillRoutine(register __a0 struct Hook *Hook,register __a1 struct {ULONG Layer; struct Rectangle Bounds;} *Bounds,register __a2 struct RastPort *RPort)
{
struct RastPort RastPort = *RPort;
RPort = &RastPort;
RPort -> Layer = NULL;
SetAPen(RPort,DrawInfo -> dri_Pens[BACKGROUNDPEN]);
SetDrMd(RPort,JAM1);
RectFill(RPort,Bounds -> Bounds . MinX,Bounds -> Bounds . MinY,Bounds -> Bounds . MaxX,Bounds -> Bounds . MaxY);
return(TRUE);
}
struct NameSegment
{
UBYTE String[63],
Separator;
};
STATIC UBYTE * __regargs
GetNameSegment(struct NameSegment *NameSegment,UBYTE *cp,WORD i)
{
UBYTE *xp = NameSegment[i] . String;
while (*cp && !strchr("._+-,@~=",*cp))
*xp++ = *cp++;
*xp = '\0';
NameSegment[i] . Separator = *cp;
if (*cp)
cp++;
if(NameSegment[i] . String[0] || NameSegment[i] . Separator)
return(cp);
else
return(NULL);
}
STATIC VOID __regargs
CopyNameSegment(struct NameSegment *NameSegment,UBYTE *Destination,WORD Zap)
{
UBYTE *cp = Destination,*xp;
for(xp = NameSegment[0] . String ; *xp ; )
*cp++ = *xp++;
if(NameSegment[0] . Separator)
{
register WORD i;
*cp++ = NameSegment[0] . Separator;
for(i = Zap + 1 ; ; i++)
{
for(xp = NameSegment[i] . String ; *xp ; )
*cp++ = *xp++;
if(NameSegment[i] . Separator)
*cp++ = NameSegment[i] . Separator;
else
{
if(!NameSegment[i] . String[0])
break;
}
}
}
*cp = 0;
}
/* ShrinkName():
*
* Shrink a file name down to a number of characters, if
* possible preserving the structure of the name. Algorithm
* courtesy of the "shrink" program by Simon Brown,
* Edinburgh University.
*/
UBYTE * __regargs
ShrinkName(const UBYTE *Source,UBYTE *Destination,WORD MaxLength,BOOLEAN FixSuffix)
{
#define MAXSEGS 10
struct NameSegment NameSegment[MAXSEGS];
WORD i,NumSegments,SuffixLength,Remainder,Delete,Total,Zap = 0;
UBYTE *OldPtr = (UBYTE *)Source;
for(i = 0 ; i < MAXSEGS && (OldPtr = GetNameSegment(NameSegment,OldPtr,i)) ; i++);
if(i < MAXSEGS)
{
NumSegments = i - 1;
if((NumSegments * 2) < MaxLength)
{
SuffixLength = strlen(NameSegment[NumSegments] . String);
if(SuffixLength > MaxLength - NumSegments - 1)
{
SuffixLength = MaxLength - (2 * NumSegments) - 1;
NameSegment[NumSegments] . String[SuffixLength - 1] = 0;
}
else
{
if (SuffixLength + NumSegments > MaxLength-NumSegments-1)
Zap = NumSegments - (MaxLength-SuffixLength)/2;
}
if(NumSegments >= 1)
{
for(i = Zap + 1 ; i <= NumSegments ; i++)
{
if(NameSegment[i] . Separator)
SuffixLength++;
}
if(NameSegment[0] . Separator)
SuffixLength++;
Remainder = MaxLength - SuffixLength;
Delete = Remainder / NumSegments;
Total = SuffixLength;
for(i = Zap + 1 ; i < NumSegments ; i++)
{
NameSegment[i] . String[Delete] = 0;
Total += Delete;
}
NameSegment[0] . String[MaxLength - Total] = 0;
}
CopyNameSegment(NameSegment,Destination,Zap);
}
else
strcpy(Destination,Source);
}
else
strcpy(Destination,Source);
if(FixSuffix)
{
BOOLEAN GotDot = FALSE;
LONG Len = strlen(Destination),Dots;
for(i = Dots = 0 ; i < Len ; i++)
{
if(Destination[i] == '.')
Dots++;
}
if(!Dots)
{
if(Len < 4)
strcat(Destination,".___");
else
Destination[Len - 4] = '.';
}
for(i = Len - 1 ; i >= 0 ; i--)
{
if(Destination[i] == '.')
{
if(GotDot)
Destination[i] = '_';
else
GotDot = TRUE;
}
if(Destination[i] == '\\')
Destination[i] = '-';
}
}
return(Destination);
}
/* BuildFontName(STRPTR Destination,const STRPTR Name,LONG Size):
*
* Build a font name and size string from given
* information (raw name and size).
*/
VOID __regargs
BuildFontName(STRPTR Destination,const STRPTR Name,LONG Size)
{
UBYTE LocalBuffer[50];
LONG Len;
strcpy(LocalBuffer,FilePart((STRPTR)Name));
Len = strlen(LocalBuffer);
if(Len > 5)
{
if(!Stricmp(&LocalBuffer[Len - 5],".font"))
LocalBuffer[Len - 5] = 0;
}
SPrintf(Destination,"%s %ld",LocalBuffer,Size);
}
/* CreateMenuGlyphs():
*
* Create scaled glyphs for pull-down menus.
*/
BOOLEAN __regargs
CreateMenuGlyphs(struct Screen *Screen,struct DrawInfo *DrawInfo,struct Image **AmigaPtr,struct Image **CheckPtr)
{
struct Image *AmigaGlyph,
*CheckGlyph;
LONG AspectX,AspectY,
Size,FontHeight;
FontHeight = DrawInfo -> dri_Font -> tf_Baseline + 2;
if(Screen -> Flags & SCREENHIRES)
Size = SYSISIZE_MEDRES;
else
Size = SYSISIZE_LOWRES;
AspectX = DrawInfo -> dri_Resolution . X;
AspectY = DrawInfo -> dri_Resolution . Y;
if(AmigaGlyph = NewObject(NULL,SYSICLASS,
SYSIA_DrawInfo, DrawInfo,
SYSIA_Size, Size,
SYSIA_Which, AMIGAKEY,
IA_Left, 0,
LA_Top, 0,
IA_Width, (FontHeight * 3 * AspectY) / (2 * AspectX),
IA_Height, FontHeight,
TAG_DONE))
{
if(!(CheckGlyph = NewObject(NULL,SYSICLASS,
SYSIA_DrawInfo, DrawInfo,
SYSIA_Size, Size,
SYSIA_Which, MENUCHECK,
IA_Left, 0,
LA_Top, 0,
IA_Width, (FontHeight * AspectY) / AspectX,
IA_Height, FontHeight,
TAG_DONE)))
{
DisposeObject(AmigaGlyph);
AmigaGlyph = NULL;
}
}
if(AmigaGlyph && CheckGlyph)
{
*AmigaPtr = AmigaGlyph;
*CheckPtr = CheckGlyph;
return(TRUE);
}
else
return(FALSE);
}
/* FixName(STRPTR Name):
*
* Build a correct AmigaDOS filename.
*/
VOID __regargs
FixName(STRPTR Name)
{
WORD NameLen = strlen(Name),
i;
/* Replace special characters. */
for(i = 0 ; i < NameLen ; i++)
{
switch(Name[i])
{
case ' ':
Name[i] = '_';
break;
case ':':
Name[i] = '.';
break;
case '/':
Name[i] = '\\';
break;
case '\"':
Name[i] = '\'';
break;
}
}
/* Truncate the name. */
if(NameLen > 31)
Name[31] = 0;
}
/* ShowError(struct Window *Window,LONG Primary,LONG Secondary,STRPTR String):
*
* Display an error message, in human readable form if possible.
*/
VOID __regargs
ShowError(struct Window *Window,LONG Primary,LONG Secondary,STRPTR String)
{
STATIC LONG LocalErrors[][2] =
{
ERR_SAVE_ERROR, MSG_ERR_COULD_NOT_SAVE_FILE_TXT,
ERR_LOAD_ERROR, MSG_ERR_COULD_NOT_LOAD_FILE_TXT,
ERR_NO_MEM, MSG_ERR_NO_MEM_TXT,
ERR_OUTDATED, MSG_ERR_OUTDATED_TXT,
IFFERR_NOMEM, MSG_IFFERR_NOMEM_TXT,
IFFERR_READ, MSG_IFFERR_READ_TXT,
IFFERR_WRITE, MSG_IFFERR_WRITE_TXT,
IFFERR_SEEK, MSG_IFFERR_SEEK_TXT,
IFFERR_MANGLED, MSG_IFFERR_MANGLED_TXT,
IFFERR_NOTIFF, MSG_IFFERR_NOTIFF_TXT,
0, 0
};
STRPTR PrimaryError = NULL,
SecondaryError = NULL;
if(Primary)
{
LONG i;
for(i = 0 ; LocalErrors[i][0] ; i++)
{
if(LocalErrors[i][0] == Primary)
{
PrimaryError = LocaleString(LocalErrors[i][1]);
break;
}
}
if(!PrimaryError)
{
STATIC UBYTE __far Buffer[256];
Fault(Primary,"",Buffer,256);
PrimaryError = Buffer + 2;
}
}
if(Secondary)
{
LONG i;
for(i = 0 ; LocalErrors[i][0] ; i++)
{
if(LocalErrors[i][0] == Secondary)
{
SecondaryError = LocaleString(LocalErrors[i][1]);
break;
}
}
if(!SecondaryError)
{
STATIC UBYTE __far Buffer[256];
Fault(Secondary,"",Buffer,256);
SecondaryError = Buffer + 2;
}
}
if(PrimaryError)
{
if(String)
MyEasyRequest(Window,PrimaryError,LocaleString(MSG_GLOBAL_CONTINUE_TXT),String,SecondaryError);
else
MyEasyRequest(Window,PrimaryError,LocaleString(MSG_GLOBAL_CONTINUE_TXT),SecondaryError);
}
}
struct RendezvousData * __saveds __asm
RendezvousLogin(register __a0 struct MsgPort *ReadPort,register __a1 struct MsgPort *WritePort,register __a2 struct TagItem *TagList)
{
struct RendezvousData *Data;
if(Data = (struct RendezvousData *)AllocVecPooled(sizeof(struct RendezvousData),MEMF_ANY | MEMF_CLEAR))
{
struct DataMsg Msg;
InitMsgItem(&Msg,TaskDestructor);
Msg . Type = DATAMSGTYPE_RENDEZVOUS;
Msg . Data = (UBYTE *)SysBase -> ThisTask;
Forbid();
ClrSignal(SIGBREAKF_CTRL_F);
PutMsgItem(SpecialQueue,(struct MsgItem *)&Msg);
Wait(SIGBREAKF_CTRL_F);
Permit();
if(ReadRequest && WriteRequest)
{
struct List *UploadList;
CopyMem(ReadRequest,&Data -> rd_ReadRequest,sizeof(struct IOExtSer));
Data -> rd_ReadRequest . IOSer . io_Message . mn_ReplyPort = ReadPort;
CopyMem(WriteRequest,&Data -> rd_WriteRequest,sizeof(struct IOExtSer));
Data -> rd_WriteRequest . IOSer . io_Message . mn_ReplyPort = WritePort;
if(Window)
Data -> rd_Screen = Window -> WScreen;
NewList(&Data -> rd_UploadList);
NewList(&Data -> rd_DownloadList);
NewList(&Data -> rd_SentList);
NewList(&Data -> rd_ReceivedList);
if(UploadList = GetUploadList())
{
struct Node *Node,*Next;
for(Node = UploadList -> lh_Head ; Next = Node -> ln_Succ ; Node = Next)
AddTail(&Data -> rd_UploadList,Node);
FreeVecPooled(UploadList);
}
Data -> rd_SendPath = Config -> PathConfig -> BinaryUploadPath;
Data -> rd_ReceivePath = Config -> PathConfig -> BinaryDownloadPath;
Data -> rd_Options = "";
}
else
{
FreeVecPooled(Data);
Data = NULL;
}
}
return(Data);
}
VOID __saveds __asm
RendezvousLogoff(register __a0 struct RendezvousData *Data)
{
if(Data)
{
struct Node *Node,*Next;
for(Node = Data -> rd_UploadList . lh_Head ; Next = Node -> ln_Succ ; Node = Next)
FreeVecPooled(Node);
for(Node = Data -> rd_DownloadList . lh_Head ; Next = Node -> ln_Succ ; Node = Next)
FreeVecPooled(Node);
for(Node = Data -> rd_SentList . lh_Head ; Next = Node -> ln_Succ ; Node = Next)
FreeVecPooled(Node);
for(Node = Data -> rd_ReceivedList . lh_Head ; Next = Node -> ln_Succ ; Node = Next)
FreeVecPooled(Node);
FreeVecPooled(Data);
Signal(ThisProcess,SIG_HANDSHAKE);
}
}
struct Node * __saveds __asm
RendezvousNewNode(register __a0 STRPTR Name)
{
if(Name)
{
LONG Len;
if(Len = strlen(Name))
{
struct Node *Node;
if(Node = (struct Node *)AllocVecPooled(sizeof(struct Node) + Len + 1,MEMF_ANY))
{
memset(Node,0,sizeof(struct Node));
strcpy(Node -> ln_Name = (STRPTR)(Node + 1),Name);
return(Node);
}
}
}
return(NULL);
}
struct List * __regargs
BuildModeList(LONG *Index,ULONG DisplayMode,ULONG (* __asm ModeFilter)(register __a1 ULONG ID))
{
struct List *List;
LONG Count = 0;
*Index = 0;
if(List = (struct List *)AllocVecPooled(sizeof(struct List),MEMF_ANY))
{
struct DisplayInfo DisplayInfo;
ULONG SomeMode = INVALID_ID;
NewList(List);
while((SomeMode = NextDisplayInfo(SomeMode)) != INVALID_ID)
{
if(GetDisplayInfoData(NULL,(APTR)&DisplayInfo,sizeof(struct DisplayInfo),DTAG_DISP,SomeMode))
{
if((DisplayInfo . PropertyFlags & DIPF_IS_WB) && !DisplayInfo . NotAvailable)
{
STRPTR Name;
if(ModeFilter)
{
if(!(*ModeFilter)(SomeMode))
continue;
}
if(Name = GetModeName(SomeMode))
{
struct ModeNode *ModeNode;
if(ModeNode = (struct ModeNode *)AllocVecPooled(sizeof(struct ModeNode) + strlen(Name) + 1,MEMF_ANY))
{
ModeNode -> VanillaNode . ln_Name = (STRPTR)(ModeNode + 1);
strcpy(ModeNode -> VanillaNode . ln_Name,Name);
ModeNode -> DisplayID = SomeMode;
AddTail(List,ModeNode);
Count++;
}
}
}
}
}
}
if(Count)
{
struct ModeNode *Node,
*Next;
for(Node = (struct ModeNode *)List -> lh_Head ; Node -> VanillaNode . ln_Succ ; Node = (struct ModeNode *)Node -> VanillaNode . ln_Succ)
{
if(!(Node -> DisplayID & MONITOR_ID_MASK))
{
for(Next = (struct ModeNode *)List -> lh_Head ; Next -> VanillaNode . ln_Succ ; Next = (struct ModeNode *)Next -> VanillaNode . ln_Succ)
{
if((Node -> DisplayID & ~MONITOR_ID_MASK) == (Next -> DisplayID & ~MONITOR_ID_MASK) && Next != Node)
Node -> DisplayID = INVALID_ID;
}
}
for(Next = (struct ModeNode *)List -> lh_Head ; Next -> VanillaNode . ln_Succ ; Next = (struct ModeNode *)Next -> VanillaNode . ln_Succ)
{
if(Node -> DisplayID == Next -> DisplayID && Next != Node)
Next -> DisplayID = INVALID_ID;
}
}
for(Node = (struct ModeNode *)List -> lh_Head ; Next = (struct ModeNode *)Node -> VanillaNode . ln_Succ ; Node = Next)
{
if(Node -> DisplayID == INVALID_ID)
{
Count--;
Remove(Node);
FreeVecPooled(Node);
}
}
}
if(Count)
{
struct ModeNode *Node,
*Next;
for(Count = 0, Node = (struct ModeNode *)List -> lh_Head ; Next = (struct ModeNode *)Node -> VanillaNode . ln_Succ ; Node = Next)
{
if(Node -> DisplayID == DisplayMode)
{
*Index = Count;
break;
}
}
return(List);
}
else
{
DeleteList(List);
return(NULL);
}
}
/* IsAssign(STRPTR Name):
*
* Does a name refer to an assignment?
*/
BOOLEAN __regargs
IsAssign(STRPTR Name)
{
WORD NameLen = strlen(Name) - 1;
BOOLEAN Result = FALSE;
/* Does it end with a colon? */
if(Name[NameLen] == ':')
{
struct DosList *DosList;
/* Lock the list of assignments for reading. */
DosList = AttemptLockDosList(LDF_ASSIGNS | LDF_READ);
/* Make sure the v37 bug doesn't catch us. */
if(((ULONG)DosList) > 1)
{
STRPTR AssignName;
/* Scan the list... */
while(DosList = NextDosEntry(DosList,LDF_ASSIGNS))
{
/* Convert the name from icky
* BCPL to `C' style string.
*/
AssignName = (STRPTR)BADDR(DosList -> dol_Name);
/* Does the name length match? */
if(AssignName[0] == NameLen)
{
/* Does the name itself match? */
if(!Strnicmp(&AssignName[1],Name,NameLen))
{
Result = TRUE;
break;
}
}
}
/* Unlock the list of assignments. */
UnLockDosList(LDF_ASSIGNS | LDF_READ);
}
}
/* Return the result. */
return(Result);
}
/* LockInAssign(BPTR TheLock,STRPTR TheAssignment):
*
* Check if a file lock is part of an assignment.
*/
BOOLEAN __regargs
LockInAssign(BPTR TheLock,STRPTR TheAssignment)
{
struct DevProc *DevProc = NULL;
struct MsgPort *FileSysTask = GetFileSysTask();
BOOLEAN Result = FALSE;
/* Loop until all assignments are
* processed.
*/
do
{
/* Get the default filesystem task
* in case we stumble upon NULL
* directory locks.
*/
if(DevProc = GetDeviceProc(TheAssignment,DevProc))
{
/* Set the default filesystem task. */
SetFileSysTask(DevProc -> dvp_Port);
/* Is the lock on the list? */
if(SameLock(DevProc -> dvp_Lock,TheLock) == LOCK_SAME)
Result = TRUE;
}
else
break;
}
while(DevProc && (DevProc -> dvp_Flags & DVPF_ASSIGN) && !Result);
/* Reset the default filesystem task. */
SetFileSysTask(FileSysTask);
/* Free device process data. */
if(DevProc)
FreeDeviceProc(DevProc);
return(Result);
}